# coding: utf-8
import os
from Tkinter import *
from tkFileDialog import askopenfilename, asksaveasfilename
from tkMessageBox import showinfo

from utils.FileOperator import FileOperator


class EasyEditor:
    def __init__(self, rt, file_name):
        if rt is None:
            self.root = Tk()
        else:
            self.root = Toplevel(rt)

        # self.root = Tk()
        self.root.title(file_name)
        self.root.geometry("800x500+100+100")

        # create menu
        menubar = Menu(self.root)
        self.root.config(menu=menubar)
        # StatusBar(self.root)
        # LinePanel(self.root)
        self.editor_frame = Frame(self.root)
        self.editor = Editor(self.editor_frame).get_editor()
        # FileMenu(self.root, menubar, self.editor)
        EditMenu(self.root, menubar, self.editor)
        menubar.add_cascade(label='刷新', command=self.load)
        menubar.add_cascade(label='保存', command=self.save)

        searchFrame = SearchFrame(self.root, self.editor)

        self.editor_frame.pack(side=TOP, expand=True, fill=BOTH)

        self.fp = FileOperator(file_name)
        self.load()

        if rt is None:
            self.root.mainloop()

    def init(self):
        self.frame_btn = Frame(self.root)
        self.frame_btn.pack(side=TOP, anchor=W)
        self.btn_save = Button(self.frame_btn, text="Save", command=self.save)
        self.btn_save.pack(side=LEFT)
        self.btn_refresh = Button(self.frame_btn, text="Refresh", command=self.load)
        self.btn_refresh.pack(side=LEFT)
        self.load()

    def save(self):  # 定义按钮事件处理函数
        self.fp.set_ini(self.editor.get(1.0, "end"))
        self.fp.save()

    def load(self):  # 定义按钮事件处理函数
        """取消返回处理"""
        self.fp.load()
        self.editor.delete(1.0, "end")
        self.editor.insert(1.0, self.fp.get_ini())


class UIBase:
    def __init__(self, root):
        self.root = root


class FileMenu(UIBase):
    def __init__(self, root, menubar, editor):
        UIBase.__init__(self, root)
        self.textpad = editor
        filemenu = Menu(menubar)
        filemenu.add_command(label='新建', accelerator='ctrl + N', command=self.neweditor)
        filemenu.bind_all("<Control-n>", self.neweditor)
        # filemenu.add_separator()
        filemenu.add_command(label='打开', accelerator='ctrl + O', command=self.openfile)
        filemenu.bind_all("<Control-o>", self.openfile)
        filemenu.add_command(label='保存', accelerator='ctrl + S', command=self.savefile)
        filemenu.bind_all("<Control-s>", self.savefile)
        filemenu.add_command(label='另存为', accelerator='ctrl + D', command=self.saveasfile)
        filemenu.bind_all("<Control-d>", self.saveasfile)
        menubar.add_cascade(label='文件', menu=filemenu)

        self.filename = ""

    # 新建
    def neweditor(self, event=None):
        self.root.title('未命名文件')
        self.filename = None
        self.textpad.delete(1.0, END)

    # 打开
    def openfile(self, event=None):
        self.filename = askopenfilename(defaultextension='.txt')
        if self.filename == '':
            self.filename = None
        else:
            self.root.title('FileName:' + os.path.basename(self.filename))
            self.textpad.delete(1.0, END)
            f = open(self.filename, 'r')
            self.textpad.insert(1.0, f.read())
            f.close()

    # 保存
    def savefile(self, event=None):
        try:
            f = open(self.filename, 'w')
            msg = self.textpad.get(1.0, END)
            f.write(msg)
            f.close()
        except Exception as e:
            print e
            self.saveasfile()

    # 另存为
    def saveasfile(self, event=None):
        f = asksaveasfilename(initialfile='未命名.txt', defaultextension='.txt')
        self.filename = f
        fh = open(f, 'w')
        msg = self.textpad.get(1.0, END)
        fh.write(msg)
        fh.close()
        self.root.title('FileName:' + os.path.basename(f))


# class SearchPanel:
#     def __init__(self, root):
#         self.keyword = ""
#         var = StringVar()
#         topsearch = Toplevel(root)
#         topsearch.geometry('300x30+200+250')
#         label1 = Label(topsearch, text='Find')
#         label1.grid(row=0, column=0, padx=5)
#         self.entry1 = Entry(topsearch, width=20)
#         self.entry1.grid(row=0, column=1, padx=5)
#         button1 = Button(topsearch, text='查找', command=self.find_char)


class EditMenu(UIBase):
    def __init__(self, root, menubar, editor):
        UIBase.__init__(self, root)
        self.textpad = editor
        self.keyword = ""
        # self.searchDialog = SearchDialog(self.root, self.textpad, self.keyword)
        # self.searchDialog.topsearch.withdraw()
        editmenu = Menu(menubar)
        editmenu.add_command(label='撤销', accelerator='ctrl + z', command=self.undo)
        # editmenu.bind_all("<Control-z>", self.undo)
        editmenu.add_command(label='重做', accelerator='ctrl + y', command=self.redo)
        # editmenu.bind_all("<Control-y>", self.redo)
        editmenu.add_command(label='复制', accelerator='ctrl + c', command=self.copy)
        # editmenu.bind_all("<Control-c>", self.copy)
        editmenu.add_command(label='剪切', accelerator='ctrl + x', command=self.cut)
        # editmenu.bind_all("<Control-x>", self.cut)
        editmenu.add_command(label='粘贴', accelerator='ctrl + v', command=self.paste)
        # editmenu.bind_all("<Control-v>", self.paste)
        # editmenu.add_command(label='查找', accelerator='ctrl + F', command=self.find_char)
        # editmenu.bind_all("<Control-f>", self.find_char)
        editmenu.add_command(label='全选', accelerator='ctrl + A', command=self.select_all)
        editmenu.bind_all("<Control-a>", self.select_all)
        menubar.add_cascade(label='编辑', menu=editmenu)

    def cut(self, event=None):
        self.textpad.event_generate('<<Cut>>')

    def copy(self, event=None):
        self.textpad.event_generate('<<Copy>>')

    def paste(self, event=None):
        self.textpad.event_generate('<<Paste>>')

    def redo(self, event=None):
        self.textpad.event_generate('<<Redo>>')

    def undo(self, event=None):
        self.textpad.event_generate('<<Undo>>')

    def select_all(self, event=None):
        self.textpad.tag_add('sel', '1.0', END)

    def find_char(self, event=None):
        # if self.searchDialog.topsearch.re:
        #     self.searchDialog.topsearch.update()
        #     self.searchDialog.topsearch.deiconify()
        # else:
        #     self.searchDialog = SearchDialog(self.root, self.textpad, self.keyword)

        searchDialog = SearchDialog(self.root, self.textpad, self.keyword)
        self.root.wait_window(searchDialog.topsearch)  # 等待对话框结束
        self.keyword = searchDialog.keyword.get()


class SearchFrame:
    def __init__(self, master, editor):
        self.textpad = editor
        self.keyword = StringVar()
        self.search_frame = Frame(master)
        label1 = Label(self.search_frame, text='搜索：')
        label1.grid(row=0, column=0, padx=5)
        entry1 = Entry(self.search_frame, width=20, textvariable=self.keyword)
        entry1.grid(row=0, column=1, padx=5)
        button1 = Button(self.search_frame, text='查找', command=self.search_text)
        button1.grid(row=0, column=2)
        entry1.focus()
        self.label_result = Label(self.search_frame, text='')
        self.label_result.grid(row=0, column=3)
        self.search_frame.pack(side=TOP, anchor=W)

    def search_text(self):
        target = self.keyword.get()
        if target:
            current = self.textpad.index("insert")
            print(current)
            end = self.textpad.index("end")
            endindex = end.split(".")
            end_line = int(endindex[0])
            end_column = int(endindex[1])
            current_index = current.split(".")
            pos_line = int(current_index[0])
            pos_column = int(current_index[1])
            length = len(target)

            "处理从头开始"
            if pos_line == end_line and pos_column + length > end_column:
                pos_line = 1
                pos_column = 0
                print "start from head"

            pos = str(pos_line) + "." + str(pos_column)
            where = self.textpad.search(target, pos, "end")
            if where:
                print(where)
                self.label_result.config({"text": where.replace(".", "/")})
                where1 = where.split(".")
                sele_end_col = str(int(where1[1]) + length)
                sele = where1[0] + "." + sele_end_col
                self.textpad.tag_add("sel", where, sele)
                self.textpad.mark_set("insert", sele)
                self.textpad.see("insert")
                self.textpad.focus()
            else:
                print "no matched!"
                # showinfo('Search', 'no matched!')
                self.label_result.config({"text": "no matched!"})


class SearchDialog:
    def __init__(self, root, editor, keyword):
        self.textpad = editor
        self.keyword = StringVar()
        self.keyword.set(keyword)
        self.topsearch = Toplevel(root)
        label1 = Label(self.topsearch, text='Find')
        label1.grid(row=0, column=0, padx=5)
        entry1 = Entry(self.topsearch, width=20, textvariable=self.keyword)
        entry1.grid(row=0, column=1, padx=5)
        button1 = Button(self.topsearch, text='查找', command=self.search_text)
        button1.grid(row=0, column=2)
        entry1.focus()
        # self.topsearch.geometry('300x30+200+250')

    def search_text(self):
        target = self.keyword.get()
        if target:
            current = self.textpad.index("insert")
            print(current)
            end = self.textpad.index("end")
            endindex = end.split(".")
            end_line = int(endindex[0])
            end_column = int(endindex[1])
            current_index = current.split(".")
            pos_line = int(current_index[0])
            pos_column = int(current_index[1])
            length = len(target)

            "处理从头开始"
            if pos_line == end_line and pos_column + length > end_column:
                pos_line = 1
                pos_column = 0
                print "start from head"

            pos = str(pos_line) + "." + str(pos_column)
            where = self.textpad.search(target, pos, "end")
            if where:
                print(where)
                where1 = where.split(".")
                sele_end_col = str(int(where1[1]) + length)
                sele = where1[0] + "." + sele_end_col
                self.textpad.tag_add("sel", where, sele)
                self.textpad.mark_set("insert", sele)
                self.textpad.see("insert")
                self.textpad.focus()
            else:
                print "no match!"
                showinfo('Search', 'no match!')


class AboutMenu(UIBase):
    def __init__(self, root):
        UIBase.__init__(self, root)
        aboutmenu = Menu(self.root)
        aboutmenu.add_command(label='作者', command=self.author)
        aboutmenu.add_command(label='版权', command=self.about)
        self.root.add_cascade(label='关于', menu=aboutmenu)

    # 关于
    def author(self):
        showinfo('作者信息', '本软件由可爱的奔奔完成')

    def about(self):
        showinfo('版权信息.copyright', '版权属于奔奔')


class StatusBar(UIBase):
    def __init__(self, root):
        UIBase.__init__(self, root)
        # statusbar
        status = Label(root, text='Ln20', bd=1, relief=SUNKEN, anchor='w')
        status.pack(side=BOTTOM, fill=X)


# class LinePanel(UIBase):
#     def __init__(self, root):
#         UIBase.__init__(self, root)
#         # 正文编辑区域
#         lnlabel = Label(root, width=2, bg='antique white')
#         lnlabel.pack(side=LEFT, fill=Y)


class Editor(UIBase):
    def __init__(self, root):
        UIBase.__init__(self, root)
        # 正文编辑区域
        # lnlabel = Label(root, width=2, bg='antique white')
        # lnlabel.pack(side=LEFT, fill=Y)

        self.textpad = Text(root, undo=True)
        scroll = Scrollbar(root)
        scroll.pack(side=RIGHT, fill=Y)
        self.textpad.config(yscrollcommand=scroll.set)
        self.textpad.pack(side=LEFT, expand=True, fill=BOTH)
        scroll.config(command=self.textpad.yview)

    def get_editor(self):
        return self.textpad


if __name__ == "__main__":
    EasyEditor(rt=None, file_name="debug.ini")
